package com.springboot.mail.modules.User.service.impl;


import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.springboot.mail.common.ResultUtil;
import com.springboot.mail.common.bean.DeleteDTO;
import com.springboot.mail.common.bean.MyResult;
import com.springboot.mail.common.bean.PageQueryDTO;
import com.springboot.mail.common.constant.RoleEnum;
import com.springboot.mail.modules.User.domain.entity.UserDO;
import com.springboot.mail.modules.User.domain.vo.ResponseLoginVO;
import com.springboot.mail.modules.User.domain.vo.UserVO;
import com.springboot.mail.modules.User.mapper.UserMapper;
import com.springboot.mail.modules.User.service.UserService;
import com.springboot.mail.modules.email.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
public class UserServiceImpl extends MPJBaseServiceImpl<UserMapper, UserDO> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Resource
    private EmailService emailService;

    @Override
    public MyResult<Page<UserVO>> getInfoPageBy(PageQueryDTO pageQueryDTO, UserVO userVO) {

        String userId = this.getLoginUserId();
        System.out.println("userId = " + userId);

        // 连表求总数。s
        MPJLambdaWrapper<UserDO> countWrapper = new MPJLambdaWrapper<UserDO>()
                .likeIfExists(UserDO::getUsername, userVO.getUsername());
        Long total = userMapper.selectJoinCount(countWrapper);

        // 连表分页查询。
        MPJLambdaWrapper<UserDO> lambdaWrapper = new MPJLambdaWrapper<UserDO>().selectAll(UserDO.class)
                .likeIfExists(UserDO::getUsername, userVO.getUsername());

        Page<UserVO> userVOIPage = userMapper.selectJoinPage(
                pageQueryDTO.toPage(pageQueryDTO.getCurrent(), pageQueryDTO.getSize(), total, false)
                , UserVO.class, lambdaWrapper);
        System.out.println(userVOIPage.getRecords());//获取分页记录
        System.out.println(userVOIPage.getPages());//总页数
        System.out.println(userVOIPage.getTotal());//总记录数
        System.out.println(userVOIPage.hasPrevious());//是否有上一页
        System.out.println(userVOIPage.hasNext());//是否有下一页
        return ResultUtil.success(userVOIPage);
    }

    @Override
    public MyResult<String> rePassword(String id) {
        UserDO userDO = new UserDO();
        userDO.setUserId(id);
        userDO.setPassword("123456");
        return userMapper.updateById(userDO) > 0 ? ResultUtil.success("密码重置成功！") : ResultUtil.error("密码重置失败！");
    }

    @Override
    public MyResult<String> setStatus(String id) {
        UserDO userDO = userMapper.selectById(id);
        if (userDO == null) {
            return ResultUtil.error("账号不存在！！");
        }
        userDO.setUserId(id);
        // 0：未禁用。1：禁用。
        userDO.setStatus(userDO.getStatus() == 0 ? 1 : 0);
        return userMapper.updateById(userDO) > 0 ? ResultUtil.success("账号状态更改成功！") : ResultUtil.error("账号状态更改失败！");
    }

    @Override
    public MyResult<String> deleteInfo(String id) {
        return userMapper.deleteById(id) > 0 ? ResultUtil.success("注销账号成功！") : ResultUtil.error("注销账号失败！");
    }


















    /**
     * 获取当前登录的用户ID
     *
     * @return
     */
    private String getLoginUserId() {
        return StpUtil.getLoginId().toString().split("_")[1];
    }


    @Override
    public MyResult<Boolean> registerUser(UserVO user) {
        // 验证码判断
        MyResult<Boolean> booleanMyResult = emailService.checkEmail(user.getEmail(), user.getEmailCode());
        if (!booleanMyResult.isResultStatus()) {
            return ResultUtil.error("验证码错误！");
        }

        // 判断用户名是否存在。
        if (this.getUserByUsername(user.getUsername()).isResultStatus()) {
            return ResultUtil.error("用户名已注册！");
        }

        // 设置注册时间
        user.setRegisterDate(new Date());
        // 插入用户数据到数据库
        int insertResult = userMapper.insert(user);
        return insertResult > 0 ? ResultUtil.success(true) : ResultUtil.error("注册失败！");
    }

    @Override
    public MyResult<ResponseLoginVO> loginUser(String username, String password) {
        UserDO userDO = userMapper.selectOne(new QueryWrapper<UserDO>().lambda()
                .eq(UserDO::getUsername, username)
                .eq(UserDO::getPassword, password));

        if (userDO == null) {
            return ResultUtil.error("账号或密码错误！");
        }
        // `SaLoginModel`为登录参数Model，其有诸多参数决定登录时的各种逻辑，【记住我模式】 例如：
        StpUtil.login(userDO.getRole() + "_" + userDO.getUserId(), new SaLoginModel()
                        .setDevice(StpUtil.getLoginDevice())                // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
                        .setIsLastingCookie(true)        // 是否为持久Cookie（临时Cookie在浏览器关闭时会自动删除，持久Cookie在重新打开后依然存在）
                        .setTimeout(60 * 60 * 24 * 7)    // 指定此次登录token的有效期, 单位:秒 （如未指定，自动取全局配置的 timeout 值）
//                .setToken("xxxx-xxxx-xxxx-xxxx") // 预定此次登录的生成的Token
                        .setIsWriteHeader(true)         // 是否在登录后将 Token 写入到响应头
        );
        userDO.setPassword("******");
        // token。
        return ResultUtil.success(new ResponseLoginVO(userDO, StpUtil.getTokenValue()));
    }

    @Override
    public MyResult<String> logout() {
        // StpUtil.logout() 在未登录时也是可以调用成功的，
        // 也就是说，无论客户端有没有登录，执行完 StpUtil.logout() 后，都会处于未登录状态
        System.out.println("当前是否处于登录状态：" + StpUtil.isLogin());

        // 退出登录会清除三个地方的数据：
        // 		1、Redis中保存的 Token 信息
        // 		2、当前请求上下文中保存的 Token 信息
        // 		3、Cookie 中保存的 Token 信息（如果未使用Cookie模式则不会清除）
        StpUtil.logout();

        // 返回给前端
        return ResultUtil.success("退出登录成功");
    }

    @Override
    public MyResult<String> addUserInfo(UserVO userVO) {
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUsername, userVO.getUsername()));
        if (user != null) {
            return ResultUtil.error("学号已存在！请勿重复添加！");
        }


        // 默认值。
        userVO.setUserId(null);
        userVO.setRole(RoleEnum.STUDENT.getValue());
        userVO.setRegisterDate(new Date());
        return userMapper.insert(userVO) > 0 ? ResultUtil.success("学员添加成功！") : ResultUtil.error("学员添加失败！");
    }

    @Override
    public MyResult<String> delUserInfo(String userId) {
        return userMapper.deleteById(userId) > 0 ? ResultUtil.success("学员删除成功！") : ResultUtil.error("学员不存在，请重新操作！");
    }

    @Override
    public MyResult<String> delUserInfo(DeleteDTO<String> deleteIds) {
        int successNum = userMapper.deleteByIds(deleteIds.getIdList());
        return successNum > 0 ? ResultUtil.success("学员删除成功！共删除：" + successNum + "条") : ResultUtil.error("学员不存在，请重新操作！");
    }


    @Override
    public MyResult<UserVO> getUserById(String userId) {

        UserVO userVO = userMapper.selectJoinOne(UserVO.class, null);
//        System.out.println("userVO = " + userVO);
        return ResultUtil.success(userVO);
    }

    @Override
    public MyResult<UserVO> getUserByUsername(String username) {
        UserVO userVO = userMapper.selectJoinOne(UserVO.class, new MPJLambdaWrapper<UserDO>().eq(UserDO::getUsername, username));
//        System.out.println("userVO = " + userVO);
        return userVO != null ? ResultUtil.success(userVO) : ResultUtil.error("用户不存在！");
    }

    @Override
    public MyResult<List<UserVO>> getTeacherList() {
        MPJLambdaWrapper<UserDO> lambdaWrapper = new MPJLambdaWrapper<UserDO>()
                .select(UserDO::getUserId, UserDO::getUsername, UserDO::getName, UserDO::getRole, UserDO::getAvatarUrl)
                .eq(UserDO::getRole, RoleEnum.TEACHER);
        return ResultUtil.success(userMapper.selectJoinList(UserVO.class, lambdaWrapper));
    }

    @Override
    public MyResult<IPage<UserVO>> getStudentInfoPageBy(PageQueryDTO pageQueryDTO, UserVO userVO) {
//        // 连表求总数。s
//        MPJLambdaWrapper<UserDO> countWarpper = new MPJLambdaWrapper<UserDO>()
//                .leftJoin(ClassInfoDO.class, ClassInfoDO::getTeacherId, "t", UserDO::getUserId)
//                .leftJoin(UserDO.class, "c", UserDO::getClassId, ClassInfoDO::getClassId)
//                .eq("t", UserDO::getUserId, StpUtil.getLoginId().toString().split("_")[1])
//                .likeIfExists("c", UserDO::getName, userVO.getName())
//                .eqIfExists(ClassInfoDO::getClassId, userVO.getClassId())
//                .isNotNull("c", UserDO::getUserId)
//                .likeIfExists("c", UserDO::getUsername, userVO.getUsername())
//                .likeIfExists(ClassInfoDO::getClassName, userVO.getClassName());
//        Long total = userMapper.selectJoinCount(countWarpper);
//
//        // 连表分页查询。
//        MPJLambdaWrapper<UserDO> lambdaWrapper = new MPJLambdaWrapper<UserDO>()
//                .selectAll(ClassInfoDO.class)
//                .selectAll(UserDO.class, "c")
//                .leftJoin(ClassInfoDO.class, ClassInfoDO::getTeacherId, UserDO::getUserId)
//                .leftJoin(UserDO.class, "c", UserDO::getClassId, ClassInfoDO::getClassId)
//                .eq(UserDO::getUserId, StpUtil.getLoginId().toString().split("_")[1])
//                .likeIfExists("c", UserDO::getName, userVO.getName())
//                .eqIfExists(ClassInfoDO::getClassId, userVO.getClassId())
//                .isNotNull("c", UserDO::getUserId)
//                .likeIfExists("c", UserDO::getUsername, userVO.getUsername())
//                .likeIfExists(ClassInfoDO::getClassName, userVO.getClassName())
//                .orderByAsc("c", UserDO::getUserId);
//
//        Page<UserVO> userVOIPage = userMapper.selectJoinPage(
//                pageQueryDTO.toPage(pageQueryDTO.getCurrent(), pageQueryDTO.getSize(), total, false)
//                , UserVO.class
//                , lambdaWrapper);
////        System.out.println(userVOIPage.getRecords());//获取分页记录
////        System.out.println(userVOIPage.getPages());//总页数
////        System.out.println(userVOIPage.getTotal());//总记录数
////        System.out.println(userVOIPage.hasPrevious());//是否有上一页
////        System.out.println(userVOIPage.hasNext());//是否有下一页
//        return ResultUtil.success(userVOIPage);
        return null;
    }

    @Override
    public MyResult<String> changeUserInfo(UserVO userVO) {
        userVO.setRole(null);
        userVO.setRegisterDate(null);
        return userMapper.updateById(userVO) > 0 ? ResultUtil.success("信息更改成功！") : ResultUtil.error("信息更改失败！");
    }


    @Override
    public MyResult<String> changeName(String userId, String name) {
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUserId, userId));
        if (user == null) {
            return ResultUtil.error("账号已下线！请重新登录！");
        }
        user.setName(name);
        return userMapper.updateById(user) > 0 ? ResultUtil.success("名称更改成功！") : ResultUtil.error("名称更改失败！");
    }

    @Override
    public MyResult<String> changePassword(String userId, String oldPassword, String newPassword) {
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUserId, userId).eq(UserDO::getPassword, oldPassword));
        if (user == null) {
            return ResultUtil.error("旧密码错误！");
        }
        user.setPassword(newPassword);
        return userMapper.updateById(user) > 0 ? ResultUtil.success("密码更改成功！") : ResultUtil.error("修改失败！");
    }

    @Override
    public MyResult<String> changeEmail(String userId, String oldEmail, String newEmail) {
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUserId, userId).eq(UserDO::getEmail, oldEmail));
        if (user == null) {
            return ResultUtil.error("旧邮箱错误！请重新输入！");
        }
        user.setEmail(newEmail);
        return userMapper.updateById(user) > 0 ? ResultUtil.success("邮箱更改成功！") : ResultUtil.error("邮箱更改失败！");

    }

    @Override
    public MyResult<String> changePhone(String userId, String newPhone) {
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUserId, userId));
        if (user == null) {
            return ResultUtil.error("账号已下线！请重新登录！");
        }
        user.setPhone(newPhone);
        return userMapper.updateById(user) > 0 ? ResultUtil.success("手机号更改成功！") : ResultUtil.error("手机号更改失败！");

    }

    @Override
    public MyResult<String> changeAvatarUrl(String userId, String avatarUrl) {
        UserDO user = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getUserId, userId));
        if (user == null) {
            return ResultUtil.error("账号已下线！请重新登录！");
        }
        user.setAvatarUrl(avatarUrl);
        return userMapper.updateById(user) > 0 ? ResultUtil.success("头像更改成功！") : ResultUtil.error("头像更改失败！");

    }

}